/**
 *CC_FW static reference object, there should only be one place where all the static reference should be found
 */
var CC_FW = {
    Base: {
        
    },
	app : {},
	fwk : null,
	utils : {},
	modules: {},
	dao : null,
	sqlDump: null,
	addEvent : null,
	EventCache : null,
	xmlHttp : null,
	instance : null,
	instanceDao : null,
	instanceApp : null
};
/**
 * just in case you want to load the library files like jQuery etc using the framework, native Xmlhttprequest
 */
CC_FW.xmlHttp = (function() {
	if ( typeof XMLHttpRequest == 'undefined') {
		XMLHttpRequest = function() {
			try {
				return new ActiveXObject('Msxml2.XMLHTTP.6.0');
			} catch ( e ) {
			}

			try {
				return new ActiveXObject('Msxml2.XMLHTTP.3.0');
			} catch ( e ) {
			}

			try {
				return new ActiveXObject('Msxml2.XMLHTTP');
			} catch ( e ) {
			}

			throw new Error('This browser does not support XMLHttpRequest.');
		};
	}
	return XMLHttpRequest;
})();

/**
 * class that holds all the functions and classes that are commonly used
 * @class CC_FW.fwk
 * @param {Function} getFileListFunction
 * @param {Function} starterFunction
 * @return {Function}
 */
CC_FW.fwk = function(getFileListFunction, starterFunction) {
	this.jsRoot = 'js';
	this.jsLibs = 'lib';
	this.jsSrc = 'src';
	//define functions for getting the file list
	this.getFileListFunction = null;
	//define the starter function
	this.starterFunction = null;
	this.loadedFiles = new Array();
	this.errors = new Array();
	return this.init(getFileListFunction, starterFunction);
}
CC_FW.fwk.prototype = {
	init : function(getFileListFunction, starterFunction) {
		if(typeof getFileListFunction != 'undefined' && typeof starterFunction != 'undefined'){
			this.getFileListFunction = getFileListFunction;
			this.starterFunction = starterFunction;
		}
	},

	run : function() {
		$LAB.setGlobalDefaults({
			AlwaysPreserveOrder : true,
			CacheBust : true
		});
		//this.getFileListFunction();
		var that = this;
		if(this.getFileListFunction != null){
			this.getFileListFunction(function(libs, src, appFiles) {
				that._externalFileListCallBack(libs, src, appFiles)
			});
		}else{
			this.starterFunction();
		}
		return this;
	},

	_externalFileListCallBack : function(libs, src, appFiles) {
		console.log('start loading files');
		var that = this;
		if ( typeof libs == 'undefined' || libs == null) {
			console.log('calling starter function');
			return that.starterFunction();
		} else {
			return this.loadFiles(libs, function() {
				if ( typeof src == 'undefined' || src == null) {
					console.log('calling starter function');
					return that.starterFunction();
				} else {
					return that.loadFiles(src, function() {
						if ( typeof appFiles == 'undefined' || appFiles == null) {
							console.log('calling starter function');
							return that.starterFunction();
						} else {
							return that.loadFiles(appFiles, function() {
								console.log('calling starter function');
								return that.starterFunction();
							});
						}

					});
				}

			});
		}
	},

	loadFiles : function(fileList, callBack) {
		var that = this;
		return $LAB.script(fileList).wait(function() {
			that.loadedFiles = that.loadedFiles.concat(fileList);
			console.log('loaded files: ' + fileList.join(','));
			callBack.call(this);
		});
	},

	addError : function(ident, errMsg) {
		this.errors.push({
			'where' : ident,
			'desc' : errMsg
		});
	},
	getErrors : function() {
		return this.errors;
	}
};

/**
 *
 * data access object for applications, should handle websql and any other similar sql transactions
 * @class
 * @param {Object} dbName
 * @param {Object} dbVersion
 * @param {Object} dbDesc
 * @param {Object} maxSize
 */
CC_FW.dao = function() {
	this.dbInstance = null;
	this.dbName = null;
	this.dbVersion = null;
	this.dbDescription = null;
	this.dbSize = null;
	//localStorage
	this.LsNameSpace = 'CC|';
	this.queryLog = new Array();
	this.dbType = null;
	return this.init();
};

CC_FW.dao.prototype = {
	/**
	 * dao constructor
	 * @param {String} dbName
	 * @param {String} dbVersion
	 * @param {String} dbDesc
	 * @param {Number} maxSize
	 */
	init : function() {
		//this.initDb();
	},
/**
 *localStorage functions 
 */
	initLs : function(nameSpace) {
		if (this.hasLocalStorage) {
			this.LsNameSpace = nameSpace + '|';
			this.dbType = 'localStorage';
			return true;
		}
		return false;
	},
	addItemLs : function(itemObj) {
		if (this.hasLocalStorage) {
			var newId = this.transformId(this.makeUniqueId());
			var addedObj = JSON.stringify(itemObj);
			window.localStorage.setItem(newId, addedObj);
			this.queryLog.push('add-' + newId + '-' + addedObj );
			return newId;
		}
		return false;
	},

	delItemLs : function(itemId) {
		if (this.hasLocalStorage) {
			var itemId = this.transformId(itemId);
			window.localStorage.removeItem(itemId);
			this.queryLog.push('del-' + itemId);
			return true;
		}
		return false;
	},

	getItemLs : function(itemId) {
		if (this.hasLocalStorage) {
			var itemId = this.transformId(itemId);
			var item = window.localStorage.getItem(itemId);
			this.queryLog.push('get-' + itemId);
			return item
		}
		return false;
	},
	
	putItemLs: function(itemId, itemObj){
		if (this.hasLocalStorage) {
			var itemId = this.transformId(itemId);
			var item = JSON.stringify(itemObj);
			window.localStorage.setItem(itemId, item);
			this.queryLog.push('put-' + itemId + '-' + item );
			return true;
		}
		return false;
	},
	
	transformId : function(clientIdent) {
		if (clientIdent.indexOf(this.LsNameSpace == -1)) {
			return this.LsNameSpace + clientIdent;
		} else {
			return clientIdent;
		}
	},

	hasLocalStorage : function() {
		try {
			return 'localStorage' in window && window['localStorage'] !== null;
		} catch (e) {
			return false;
		}
	},

	makeUniqueId : function() {
		var randString = function() {
			return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1)
		};
		return randString() + randString() + "-" + randString() + "-" + randString() + "-" + randString() + "-" + randString() + randString() + randString() + '|';
	},
/**
 * SQL functions for websql
 */
	initDb : function(dbName, dbVersion, dbDesc, maxSize) {
		this.dbName = dbName;
		this.dbVersion = dbVersion;
		this.dbDescription = dbDesc;
		this.dbSize = maxSize;
		this.dbType = 'sql';
		var that = this;
		if ( typeof (window.openDatabase) != 'undefined' && window.openDatabase) {
			this.dbInstance = window.openDatabase(this.dbName, this.dbVersion, this.dbDescription, this.dbSize);
		} else {
			alert('database not supported')
		}
	},
	/**
	 *
	 * @param {Object} sql
	 * @param {Object} arrVals
	 * @param {Object} callBack
	 */
	queryDb : function(sql, arrVals, callBack) {
		var that = this;
		this.queryLog.push(sql + '-' + arrVals.join(',') + '-' + callBack.toString());
		this.dbInstance.transaction(function(tx) {
			//same callback for fail and success of transaction
			tx.executeSql(sql, arrVals, callBack, callBack);
		});
		return this;
	}
};
/*
 //from
 //http://www.braksator.com/how-to-make-your-own-jquery
 //http://www.dustindiaz.com/rock-solid-addevent/
 CC_FW.addEvent(window, 'unload', CC_FW.EventCache.flush);
 CC_FW.addEvent(window, 'load', function() {
 CC_FW.instance = new CC_FW.fwk();
 CC_FW.instance.run();
 });
 */

/**
 * @author ngimenez
 */
CC_FW.sqlDump = function(dbName, dbVersion, dbDesc, maxSize, sqlFile){
    this.db = null;
    this.dbName = null;
    this.dbVersion = null;
    this.dbDesc = null;
    this.maxSize = null;
    this.sqlFile = null;
    this.getSqlStatementsCallBack = null;
    return this.init(dbName, dbVersion, dbDesc, maxSize, sqlFile);
};
CC_FW.sqlDump.prototype = {
    //sqlite3 2013-01-25.db .dump > myDb.sql
    init: function(dbName, dbVersion, dbDesc, maxSize, sqlFile){
        this.dbName = dbName;
        this.dbVersion = dbVersion;
        this.dbDesc = dbDesc;
        this.maxSize = maxSize;
        this.sqlFile = sqlFile;
        this.initDb();
    },
    initDb: function(){
        this.db = window.openDatabase(this.dbName, this.dbVersion, this.dbDesc, this.maxSize);
    },
    getSqlStatements: function(callBack){
        var that = this;
        this.getSqlStatementsCallBack = callBack;
        $.get(this.sqlFile, function(response) {
            var queries = response.split(';');
            queries = queries.filter(function(res){
                if(res.match(/(INSERT|CREATE|DROP|PRAGMA|BEGIN|COMMIT)/) != null){
                    return res;
                }
            });
            that.processQuery(0, queries); 
        });
    },
    
    processQuery: function(i, queries){
        var that = this;
        var query = queries[i];
        if(i <= queries.length -1){
            if(query.match(/(INSERT|CREATE|DROP|PRAGMA|BEGIN|COMMIT)/)){
                console.log('------------>', query);
                this.db.transaction( function (tx){ 
                        tx.executeSql(query+';', [], function(tx, result) {
                            return that.processQuery(i +1, queries);  
                        });          
                    },function(err){
                        console.log("!!!!Query error in ", query, err.message);
                        return that.processQuery(i + 1, queries);
                    }
                );
            }
        }else{
            console.log("Done importing!");
            if(this.getSqlStatementsCallBack != null){
                that.getSqlStatementsCallBack("Done importing!");
            }
        }
            
    },
    
    _processQuery: function(i, queries) {
        var that = this;
        if(i < queries.length -1) {
            console.log(i +' of '+ queries.length);
            if(!queries[i+1].match(/(INSERT|CREATE|DROP|PRAGMA|BEGIN|COMMIT)/)) {
                queries[i+1] = queries[i]+ ';' + queries[i+1];
                return this._processQuery(i+1, queries);
            }
            console.log('------------>', queries[i]);
            this.db.transaction( function (tx){ 
                    tx.executeSql(queries[i]+';', [], function(tx, result) {
                        that._processQuery(i +1, queries);  
                    });          
                },function(err){
                    console.log("Query error in ", queries[i], err.message);
                    that._processQuery(i + 1, queries);
                }
            );
        } else {
            console.log("Done importing!");
            if(this.getSqlStatementsCallBack != null){
                that.getSqlStatementsCallBack("Done importing!");
            }
        }
    }
};
